use crate::model::{Alias, ServerProxy};
use crate::model::{CodeModule, LibImport};
use crate::traits::{CommonModuleTrait, ViteConfigTrait, ViteConfigUpdatedModuleTrait};

#[test]
fn test_new_code_module() {
    let ts_source_code = r#"

export const getUser = apiFactory({
  path: "/get_user",
  method: "POST",
})
export const useGetUser = () => useApi(getUser);

export type getUserRequest = {
  id: string;
  name: string
"#;
    let code_module = CodeModule::new(ts_source_code);
    assert!(code_module.is_err()); // 不支持typescript的导出语法
}
#[test]
fn test_try_get_import_none() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/'
});
"#;
    let mut code_module = CodeModule::new(ts_source_code).expect("new error");
    let result = code_module
        .update_module()
        .expect("update_module error")
        .try_get_import("path");

    assert!(result.is_none());
}

#[test]
fn test_try_get_import() {
    let ts_source_code = r#"
import {resolve} from 'path';

export default defineConfig({
    base: '/'
});
"#;
    let mut code_module = CodeModule::new(ts_source_code).expect("new error");
    let result = code_module
        .update_module()
        .expect("update_module error")
        .try_get_import("path");

    assert!(result.is_some());
}

#[test]
fn test_init_root_node_create() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/'
});
"#;
    let mut vite_config = CodeModule::new(ts_source_code).expect("new error");
    vite_config
        .init_root_node("server")
        .expect("init_server_node");

    assert_eq!(
        vite_config.get_source(),
        r#"
export default defineConfig({
  "server": {},
    base: '/'
});
"#
    );
}

#[test]
fn test_init_root_node_none1() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/',
    "server": {},
});
"#;
    let mut vite_config = CodeModule::new(ts_source_code).expect("new error");
    vite_config
        .init_root_node("server")
        .expect("init_server_node");

    assert_eq!(vite_config.get_source(), ts_source_code);
}

#[test]
fn test_init_root_node_none2() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/',
    server: {},
});
"#;
    let mut vite_config = CodeModule::new(ts_source_code).expect("new error");
    vite_config
        .init_root_node("server")
        .expect("init_server_node");

    assert_eq!(vite_config.get_source(), ts_source_code);
}

#[test]
fn test_try_get_server_node() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/',
    server: {},
});
"#;
    let mut vite_config = CodeModule::new(ts_source_code).expect("new error");
    let result = vite_config
        .update_module()
        .expect("update module error")
        .try_get_server_node();

    assert!(result.is_some());
}

#[test]
fn test_try_get_server_node_err() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/',
});
"#;
    let mut vite_config = CodeModule::new(ts_source_code).expect("new error");
    let result = vite_config
        .update_module()
        .expect("update_module error")
        .try_get_server_node();

    assert!(result.is_none());
}

#[test]
fn test_init_proxy_node_with_err() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/',
});
"#;
    let mut vite_config = CodeModule::new(ts_source_code).expect("new error");
    let result = vite_config.init_proxy_node();

    assert!(result.is_err());
}

#[test]
fn test_init_proxy_node() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/',
    "server": {}
});
"#;
    let expected_source = r#"
export default defineConfig({
    base: '/',
    "server": {  "proxy": {},
}
});
"#;
    let mut vite_config = CodeModule::new(ts_source_code).expect("new error");
    let _ = vite_config.init_proxy_node();

    assert_eq!(vite_config.get_source(), expected_source);
}

#[test]
fn test_insert_proxy() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/',
    "server": {
      "proxy": {},
    }
});
"#;
    let expected_source = r#"
export default defineConfig({
    base: '/',
    "server": {
      "proxy": {  "/api": {
  "target": "http://127.0.0.1:8080",
  "rewrite": (path)=>path.replace(/^\/api/, '')
    },
},
    }
});
"#;
    let mut vite_config = CodeModule::new(ts_source_code).expect("new error");
    let _ = vite_config
        .insert_proxy(&ServerProxy {
            route_name: "/api".to_string(),
            target: "http://127.0.0.1:8080".to_string(),
        })
        .expect("insert_proxy error");

    assert_eq!(vite_config.get_source(), expected_source);
    assert_eq!(vite_config.is_module_updated(), false);
}

#[test]
fn test_insert_alias() {
    let ts_source_code = r#"
export default defineConfig({
    base: '/',
    resolve: {
      alias: {},
    },
});
"#;
    let expected_source = r#"
export default defineConfig({
    base: '/',
    resolve: {
      alias: {
        "@": resolve(__dirname, './src'),
      },
    },
});
"#;
    let mut vite_config = CodeModule::new(ts_source_code).expect("new error");
    let _ = vite_config
        .insert_alias(&Alias {
            name: "@".to_string(),
            path: "./src".to_string(),
        })
        .expect("insert_alias error");

    assert_eq!(vite_config.get_source(), expected_source);
    assert_eq!(vite_config.is_module_updated(), false);
}

#[test]
fn test_init_pos_of_code() {
    let ts_source_code = r#"//author: zongying_cao@163.com
export default defineConfig({
    base: '/',
    resolve: {
      alias: {},
    },
});
"#;
    let mut code_module = CodeModule::new(ts_source_code).expect("new error");
    let result = code_module.get_init_pos_of_code();

    assert_eq!(result, 31);
}

#[test]
fn test_init_import() {
    let ts_source_code = r#"
// author: zongying_cao@163.com
export default defineConfig({
    base: '/',
    resolve: {
      alias: {},
    },
});
"#;
    let expected_source = r#"
// author: zongying_cao@163.com
import {resolve} from 'path';
export default defineConfig({
    base: '/',
    resolve: {
      alias: {},
    },
});
"#;
    let mut code_module = CodeModule::new(ts_source_code).expect("new error");
    let _ = code_module
        .init_import(&LibImport {
            lib_name: "path".to_string(),
            element_name: "resolve".to_string(),
            is_default: false,
            command: None,
        })
        .expect("init_import error");

    assert_eq!(code_module.get_source(), expected_source);
    assert_eq!(code_module.is_module_updated(), false);
}

#[test]
fn test_init_import_with_existing_lib() {
    let ts_source_code = r#"
// author: zongying_cao@163.com
import path from 'path';
export default defineConfig({
    base: '/',
    resolve: {
      alias: {},
    },
});
"#;
    let expected_source = r#"
// author: zongying_cao@163.com
import {resolve} from 'path';
import path from 'path';
export default defineConfig({
    base: '/',
    resolve: {
      alias: {},
    },
});
"#;
    let mut code_module = CodeModule::new(ts_source_code).expect("new error");
    let _ = code_module
        .init_import(&LibImport {
            lib_name: "path".to_string(),
            element_name: "resolve".to_string(),
            is_default: false,
            command: None,
        })
        .expect("init_import error");

    assert_eq!(code_module.get_source(), expected_source);
    assert_eq!(code_module.is_module_updated(), false);
}
